﻿using CoreCms.Net.Configuration;
using CoreCms.Net.Loging;
using Essensoft.Paylink.WeChatPay.V2.Notify;
using Essensoft.Paylink.WeChatPay.V2;
using Microsoft.AspNetCore.Mvc;
using MySqlX.XDevAPI;
using Newtonsoft.Json;
using System.Threading.Tasks;
using System;
using NLog;
using CoreCms.Net.Model.ViewModels.Pay;
using System.IO;
using System.Net.Http;
using CoreCms.Net.Model.FromBody;
using CoreCms.Net.Utility.Helper;
using CoreCms.Net.IServices;
using CoreCms.Net.Model.Entities;
using Newtonsoft.Json.Linq;
using CoreCms.Net.Utility.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Diagnostics;
using System.Collections.Generic;
using NLog.LayoutRenderers;
using System.Text;

namespace CoreCms.Net.Web.WebApi.Controllers.PayNotify
{
    /// <summary>
    /// Paynow异步通知
    /// </summary>
    [Route("Notify/[controller]/[action]")]
    [AllowAnonymous]
    public class PaynowController : ControllerBase
    {
        private readonly ICoreCmsPaymentsServices _paymentsServices;
        private readonly ICoreCmsBillPaymentsServices _billPaymentsServices;
        /// <summary>
        /// 构造函数
        /// </summary>
        public PaynowController(ICoreCmsBillPaymentsServices billPaymentsServices, ICoreCmsPaymentsServices paymentsServices)
        {
            _billPaymentsServices = billPaymentsServices;
            _paymentsServices = paymentsServices;
        }

        /// <summary>
        ///     订单支付结果通知
        /// </summary>
        [HttpPost]
        public async Task<IActionResult> NotifyOrder([FromBody] PaynowNotify payload)
        {
            try
            {
                string strFomoPay = Request.Headers["x-fomopay-authorization"].ObjectToString();
                NLogUtil.WriteAll(LogLevel.Error, LogType.Order, "request header x-fomopay-authorization", strFomoPay);
                string[] aryFomo = strFomoPay.Split(' ');
                if (aryFomo.Length != 2) throw new Exception($"x-fomopay-authorization 数据格式异常 {strFomoPay}");
                Dictionary<string, string> dic = CommonHelper.GetFomoPayData(aryFomo[1]);
                NotifyRequestHeaders requestHeaders = new NotifyRequestHeaders()
                {
                    Version = dic["version"],
                    Credential = dic["credential"],
                    Nonce = dic["nonce"],
                    Timestamp = dic["timestamp"],
                    Signature = dic["signature"]
                };
                NLogUtil.WriteAll(LogLevel.Error, LogType.Order, "notify header", JsonConvert.SerializeObject(requestHeaders));

                StringBuilder strB = new StringBuilder();
                strB.Append("{");
                if (!string.IsNullOrWhiteSpace(payload.orderId))
                    strB.Append($"\"orderId\":\"{payload.orderId}\"");
                if (!string.IsNullOrWhiteSpace(payload.orderNo))
                    strB.Append($",\"orderNo\":\"{payload.orderNo}\"");
                if (!string.IsNullOrWhiteSpace(payload.transactionId))
                    strB.Append($",\"transactionId\":\"{payload.transactionId}\"");
                if (!string.IsNullOrWhiteSpace(payload.transactionNo))
                    strB.Append($",\"transactionNo\":\"{payload.transactionNo}\"");
                strB.Append("}");
                string jsonLoad = strB.ToString();
                NLogUtil.WriteAll(LogLevel.Error, LogType.Order, "notify body", jsonLoad);
                CoreCmsPayments payInfo = await _paymentsServices.QueryByClauseAsync(a => a.code == "paynow" && a.isEnable == true);
                if (payInfo == null) throw new Exception("paynow支付方式不存在");
                NLogUtil.WriteAll(LogLevel.Error, LogType.Order, "paynow params", payInfo.parameters);
                JObject resPay = JsonConvert.DeserializeObject<JObject>(payInfo.parameters);
                string message = $"{jsonLoad}{requestHeaders.Timestamp}{requestHeaders.Nonce}";
                NLogUtil.WriteAll(LogLevel.Error, LogType.Order, "paynow message", message);
                string sign = CommonHelper.HMACSHA256(message, resPay.GetValue("psk").ObjectToString());
                if (!requestHeaders.Signature.Equals(sign))
                    throw new Exception("签名校验失败：" + message);

                var jm = await _billPaymentsServices.PaynowNotify(payload);

                NLogUtil.WriteAll(LogLevel.Error, LogType.Order, "notify callback", JsonConvert.SerializeObject(jm));

                return Ok();
            }
            catch (Exception ex)
            {
                NLogUtil.WriteAll(LogLevel.Error, LogType.Order, "Paynow支付成功回调", "订单支付结果通知", ex);
                return BadRequest(ex.Message);
            }
        }
    }
}
